package hfs

import (
	"context"
	"crypto/tls"
	"fmt"
	"net"
	"net/http"
	"sync"
	"time"

	"github.com/gin-gonic/gin"
	"github.com/quic-go/quic-go/http3"
)

type HttpFileServer interface {
	StartServer()
	StopServer()
	AddMapping(virtualDir, physicalPath string)
	RemoveMapping(virtualDir string)
	SetMappings(mappings map[string]string)
}

type httpFileServerImpl struct {
	config         *Config
	http3Server    *http3.Server
	http3Conn      net.PacketConn
	http2Server    *http.Server
	http2Listener  net.Listener
	hfsContext     context.Context
	hfsCancel      context.CancelFunc
	mappings       map[string]string
	mutex          *sync.RWMutex
	isShuttingDown bool // 标记服务器是否正在主动关闭
}

func NewHttpFileServer(config *Config) HttpFileServer {
	if config == nil {
		panic("config is nil")
	}
	return &httpFileServerImpl{
		config:      config,
		http2Server: nil,
		http3Server: nil,
		mappings:    make(map[string]string),
		mutex:       &sync.RWMutex{},
	}
}

// StartServer 启动HTTP3服务器
func (s *httpFileServerImpl) StartServer() {
	// 创建上下文用于控制服务器生命周期
	s.hfsContext, s.hfsCancel = context.WithCancel(context.Background())
	// 设置Gin为发布模式
	gin.SetMode(gin.ReleaseMode)

	// 创建Gin路由器
	router := gin.New()

	// 添加中间件
	router.Use(gin.Logger())
	router.Use(gin.Recovery())
	router.Use(s.AllowedCORSMiddleware())
	router.Use(s.StaticFileMiddleware())

	// 创建TLS配置
	tlsConfig := &tls.Config{
		InsecureSkipVerify: true, // 仅用于测试，生产环境应使用有效证书
	}

	// 加载外部证书文件
	cert, err := tls.LoadX509KeyPair(s.config.CertFile, s.config.KeyFile)
	if err != nil {
		s.config.Logger.Fatalf("加载证书文件失败: %v", err)
	}
	tlsConfig.Certificates = []tls.Certificate{cert}

	addr := fmt.Sprintf("0.0.0.0:%d", s.config.Port)

	// 创建HTTP2服务器
	if s.config.Mode == MODE_BOTH || s.config.Mode == MODE_HTTP2 {
		s.http2Listener, err = net.Listen("tcp4", addr)
		if err != nil {
			s.config.Logger.Fatalf("HttpFileServer2 监听端口失败: %v", err)
		}
		s.http2Server = &http.Server{
			Handler:   router,
			Addr:      addr,
			TLSConfig: tlsConfig,
		}
	}
	// 创建HTTP3服务器
	if s.config.Mode == MODE_BOTH || s.config.Mode == MODE_HTTP3 {
		s.http3Conn, err = net.ListenPacket("udp4", addr)
		if err != nil {
			s.config.Logger.Fatalf("HttpFileServer3 监听端口失败: %v", err)
		}

		s.http3Server = &http3.Server{
			Handler:   router,
			Addr:      addr,
			TLSConfig: tlsConfig,
		}
	}

	s.config.Logger.Infof("HttpFileServer 监听端口: %d", s.config.Port)

	// 启动服务器
	go func() {
		if s.http2Server != nil {
			if err := s.http2Server.Serve(s.http2Listener); err != nil {
				// 检查是否是因为主动关闭服务器导致的错误
				if s.isShuttingDown {
					s.config.Logger.Info("HttpFileServer/2 服务已关闭")
				} else {
					s.config.Logger.Fatalf("HttpFileServer/2 服务启动失败: %v", err.Error())
				}
			}
		}
	}()
	go func() {
		if s.http3Server != nil {
			if err := s.http3Server.Serve(s.http3Conn); err != nil {
				// 检查是否是因为主动关闭服务器导致的错误
				if s.isShuttingDown {
					s.config.Logger.Info("HttpFileServer/3 服务已关闭")
				} else {
					s.config.Logger.Fatalf("HttpFileServer/3 服务启动失败: %v", err.Error())
				}
			}
		}
	}()
	// 在另一个goroutine中等待停止信号
	go func() {
		<-s.hfsContext.Done()
		s.config.Logger.Info("收到停止信号，正在关闭HttpFileServer 服务")
	}()
}

func (s *httpFileServerImpl) StopServer() {
	// 标记服务器正在主动关闭
	s.isShuttingDown = true

	// 关闭Gin服务器
	if s.hfsCancel != nil {
		s.hfsCancel() // 发送停止信号
	}

	if s.http2Server != nil {
		ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
		defer cancel()
		if err := s.http2Server.Shutdown(ctx); err != nil {
			s.config.Logger.Errorf("HttpFileServer/2 服务关闭失败: %v", err)
		}
	}
	if s.http3Server != nil {
		ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
		defer cancel()
		if err := s.http3Server.Shutdown(ctx); err != nil {
			s.config.Logger.Errorf("HttpFileServer/3 服务关闭失败: %v", err)
		}
	}
}
